#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/init.h>
#include <linux/module.h>

#define TAG "pfs"
#define LOG_INF(format, args...)    pr_info(TAG "[%s:%d] " format, __func__, __LINE__, ##args)
#define LOG_ERR(format, args...)    pr_err(TAG "[%s:%d] " format, __func__, __LINE__, ##args)
#define MAX_POS 5
static int val[] = {1, 2,3,4,5};

struct _pfs_demo {
	struct proc_dir_entry * root;
	struct proc_dir_entry * item;
}psf;


void *proc_seq_start(struct seq_file *sfile, loff_t *pos)
{
	LOG_INF("pos=%lld\n", *pos);

	return (*pos >= MAX_POS) ? NULL : pos;
}

void *proc_seq_next(struct seq_file *sfile, void *pv, loff_t *pos)
{
	long long v = *pos;
	LOG_INF("pos=%lld\n", v);
	if(*pos >= MAX_POS){
		return NULL;
	}
	*pos += 1;
	return (void*)(val + v);

}

void proc_seq_stop(struct seq_file *sfile, void *pv)
{
	LOG_INF("\n");
}

int proc_seq_show(struct seq_file *sfile, void *pv)
{
	LOG_INF("xx");
	seq_printf(sfile, "%d ", *((int*)pv));
	return 0;
}

static struct seq_operations proc_seq_ops = {
    .start = proc_seq_start,
    .next = proc_seq_next,
    .stop = proc_seq_stop,
    .show = proc_seq_show,
};

static int proc_seq_open(struct inode *inode, struct file *filp)
{
    return seq_open(filp, &proc_seq_ops);
}

static struct file_operations fops = {
    .owner = THIS_MODULE,
//    .write = proc_write,
    .open = proc_seq_open,
    .read = seq_read,
    .llseek = seq_lseek,
    .release = seq_release,
};

static int __init demo_init(void)
{
	LOG_INF("enter");
	psf.root = proc_mkdir(TAG, NULL);
	if(!psf.root){
		LOG_ERR("proc_mkdir failed");
		return -ENODEV;
	}
	psf.item = proc_create_data("test", 0444, psf.root, &fops, NULL);

	return 0;
}

static void __exit demo_exit(void)
{
	LOG_INF("enter");
	proc_remove(psf.item);
	proc_remove(psf.root);
	return;
}

module_init(demo_init);
module_exit(demo_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("tj<tj_wust@163.com>");